package tv.acgn.advertisement.publish.service.impl;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;

import org.springframework.beans.factory.annotation.Autowired;
import tv.acgn.advertisement.publish.dao.AdPlanDao;
import tv.acgn.advertisement.publish.dao.AdUserDao;
import tv.acgn.advertisement.publish.dao.dsl.AdPlanDslDao;
import tv.acgn.advertisement.publish.exception.AbstractAdPubException;
import tv.acgn.advertisement.publish.exception.AdPlanHasExistException;
import tv.acgn.advertisement.publish.exception.AdPlanNotFoundException;
import tv.acgn.advertisement.publish.exception.UserNotFoundExceptionAbstract;
import tv.acgn.advertisement.publish.po.AdPlanPO;
import tv.acgn.advertisement.publish.service.AdPlanService;
import tv.acgn.advertisement.publish.validator.message.AdPlanValidateMessage;
import tv.acgn.advertisement.publish.vo.adplan.AdPlanGetRequestVO;
import tv.acgn.advertisement.publish.vo.adplan.AdPlanRequestVO;
import tv.acgn.advertisement.publish.vo.adplan.AdPlanResponseVO;

/**
 * @program : advertisement-ad-pub-service
 * @description : 推广计划 业务实现类
 * @author : junG
 * @date : 2019-05-01 16:19
 **/
public class AdPlanServiceImpl implements AdPlanService {

    @Autowired
    private AdPlanDao adPlanDao;
    @Autowired
    private AdUserDao adUserDao;
    @Autowired
    private AdPlanDslDao adPlanDslDao;

    @Override
    public AdPlanPO getAdPlan(@NotBlank(message = AdPlanValidateMessage.planIdNotBland)
        String adPlanId) throws AbstractAdPubException {
        AdPlanPO adPlanPO = adPlanDao.findById(adPlanId).orElseThrow(AdPlanNotFoundException::new);
        return adPlanPO;
    }

    @Override
    public AdPlanPO findAdPlanByUserIdAndPlanName(@Valid AdPlanRequestVO adPlanRequestVO)
        throws AbstractAdPubException {
        AdPlanPO adPlanPO = adPlanDao
                .findByUserIdAndPlanName(adPlanRequestVO.getUserId(), adPlanRequestVO.getPlanName())
                .orElseThrow(AdPlanNotFoundException::new);

        return adPlanPO;
    }

    @Override
    public AdPlanResponseVO addAdPlan(@Valid AdPlanRequestVO adPlanRequestVO) throws AbstractAdPubException {

        adUserDao.findById(adPlanRequestVO.getUserId())
            .orElseThrow(UserNotFoundExceptionAbstract::new);

        //TODO 查找已存在不应该 使用 空异常抛出的 orElseThrow方法
        adPlanDao.findByUserIdAndPlanName(adPlanRequestVO.getUserId(), adPlanRequestVO.getPlanName())
            .orElseThrow(AdPlanHasExistException::new);

        AdPlanPO adPlanPO = new AdPlanPO();
        adPlanPO.setPlanName(adPlanRequestVO.getPlanName())
                .setUserId(adPlanRequestVO.getUserId())
                .setStartDate(adPlanRequestVO.getStartDate())
                .setEndDate(adPlanRequestVO.getEndDate());

        AdPlanPO newAdPlanPO = adPlanDao.save(adPlanPO);

        return AdPlanResponseVO.builder()
                .adPlanId(newAdPlanPO.getPlanId())
                .planName(newAdPlanPO.getPlanName())
                .build();
    }

    @Override
    public AdPlanResponseVO updateAdPlan(@Valid AdPlanRequestVO adPlanRequestVO) throws AbstractAdPubException {

        adUserDao.findById(adPlanRequestVO.getUserId())
            .orElseThrow(UserNotFoundExceptionAbstract::new);

        AdPlanPO adPlanPO = adPlanDao.findById(adPlanRequestVO.getPlanId())
                .orElseThrow(AdPlanNotFoundException::new);

        adPlanPO.setPlanStatus(adPlanRequestVO.getPlanStatus())
                .setPlanName(adPlanRequestVO.getPlanName())
                .setStartDate(adPlanRequestVO.getStartDate())
                .setEndDate(adPlanRequestVO.getEndDate())
                .setUpdateTime(LocalDateTime.now());

        adPlanDao.save(adPlanPO);

        return AdPlanResponseVO.builder().adPlanId(adPlanPO.getPlanId()).planName(adPlanPO.getPlanName()).build();
    }

    @Override
    public AdPlanResponseVO deleteAdPlan(@NotBlank(message = AdPlanValidateMessage.planIdNotBland)
        String adPlanId) throws AbstractAdPubException {

        AdPlanPO adPlanPO = adPlanDao.findById(adPlanId)
                .orElseThrow(AdPlanNotFoundException::new);

        adPlanDao.delete(adPlanPO);

        return AdPlanResponseVO.builder().adPlanId(adPlanPO.getPlanId()).planName(adPlanPO.getPlanName()).build();
    }

    @Override
    public List<AdPlanPO> getAdPlanBatch(@NotBlank(message = AdPlanValidateMessage.planIdNotBland)
        List<String> adPlanIdList) throws AbstractAdPubException {
        List<AdPlanPO> adPlanPOList = adPlanDao.findAllById(adPlanIdList);
        return adPlanPOList;
    }

    @Override
    public List<AdPlanPO> findAllAdPlanByUserId(@Valid AdPlanGetRequestVO adPlanGetRequestVO) throws
        AbstractAdPubException {

        List<AdPlanPO> adPlanPOList = adPlanDao.
                findAllByPlanIdInAndUserId(adPlanGetRequestVO.getPlanIds(), adPlanGetRequestVO.getUserId())
                .orElseThrow(AdPlanNotFoundException::new);

        return adPlanPOList;
    }

    @Override
    public List<AdPlanPO> findAdPlan(@Valid AdPlanRequestVO adPlanRequestVO) throws AbstractAdPubException {
        AdPlanPO adPlanPO = AdPlanPO.builder()
                .userId(adPlanRequestVO.getUserId())
                .planName(adPlanRequestVO.getPlanName())
                .planStatus(adPlanRequestVO.getPlanStatus())
                .createTime(adPlanRequestVO.getCreateTime())
                .updateTime(adPlanRequestVO.getUpdateTime())
                .startDate(adPlanRequestVO.getStartDate())
                .endDate(adPlanRequestVO.getEndDate())
                .build();

        List<AdPlanPO> adPlanPOList = adPlanDslDao.findByQueryParam(adPlanRequestVO).orElseThrow(
            AdPlanNotFoundException::new);
        return adPlanPOList;
    }

    @Override
    public List<AdPlanResponseVO> deleteAdPlanBatch(@NotBlank(message = AdPlanValidateMessage.planIdNotBland)
        List<String> adPlanIdList) throws AbstractAdPubException {
        List<AdPlanPO> adPlanPOList = adPlanDao.findAllById(adPlanIdList);
        adPlanDao.deleteAll(adPlanPOList);

        List<AdPlanResponseVO> adPlanResponseVOList = adPlanPOList.stream().map(x ->
                AdPlanResponseVO.builder().adPlanId(x.getPlanId()).planName(x.getPlanName()).build()
        ).collect(Collectors.toList());

        return adPlanResponseVOList;
    }
}
